package ch.zbw.iCoach.remo;

//There are two imports needed. 
//One is ArrayList.The other one is Iterator
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

import ch.zbw.iCoach.kit.*;
import ch.zbw.iCoach.dameon.*;

/**
 * This class is dealing at the beginning of the program iCoach. It is the interface between GUI, Database
 * and active game playing.
 * 
 * @author Remo Reimann
 * @version Version 1 (release 18.03.2013)
 */
public class MainLogic {

	//this data field stores an ActiveUser reference, called "activeUser"
	private ActiveUser activeUser;
	//this data field stores an UserList reference, called "userList"
	private UserList userList;
	//this data field stores a LanguageList reference, called "langList"
	private LanguageList langList;
	//this data field stores a DataHandlingIO reference, called "dataHandlingIO"
	private DataHandlingIO dataHandlingIO;
	//this data field stores a WelcomeScreen reference, called "welcomeScreen"
	private WelcomeScreen welcomScreen;
	//this data field stores a Message reference, called "message"
	private Message	message;
	//this data field stores an index, which is needed for deleting a word
	private int deletingIndex;

	
	/**
	 * This constructor works without any handover values!
	 * 
	 * The MainLogic is a kind of interface class. It is needed for the interfaces between GUI, 
	 * gameplay and the database (ArrayLists).
	 * 
	 * First, it initializes a new UserList instance. UserList works with a handover less
	 * constructor, too.  
	 * Second, the program initializes a WelcomScreen instance. This is the first GUI unit, which the 
	 * user can see. In this case are handover values needed. WelcomeScreen require an UserList and a MainLogic
	 * reference.
	 */
	public MainLogic(){
		
		//Initialisation of a new UserList instance. Later the program stores the reference in the
		//data field "userList"
		this.userList = new UserList();
		//A new instance of the class Languagelist will be created and stored into the variable
		//"langList".
		this.langList = new LanguageList();
		//A new instance of the class DataHandlingIO will be created and stored into the variable
		//"dataHanlingIO".
		this.dataHandlingIO = new DataHandlingIO(langList, userList);
		//Try-Catch block surrounding the "loadGame" method. It could happen that there is no file in the filesystem.
		try {
			//query the method loadGame.
			this.loadGame();
		} catch (Exception e) {
			// If there is no file, a console massage will be created.
			System.out.println("Language file doesn't exist. Hang on, a default template will be loaded");
		}
		
		//At this point a default word list will be loaded, if there are no specific Language List. 
		//The handover value is to mark the default words
		if (langList.getSize() <= 0){
			this.dataHandlingIO.startUp("default");
		}
		//Try-Catch block surrounding the "loadUser" method. It could happen that there is no file in the filesystem.
		try {
			//query the method loadUser.
			this.loadUsers();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("File doesn't exist. Hang on, a default template will be loaded");
		}
		//Initialisation of a new UserList instance. Later the program stores the reference in the
		//data field "userList". 
		//"this" in the values list gives WelcomeScreen a reference to this instance. 
		this.welcomScreen = new WelcomeScreen(this.userList, this);
		//This index is initialised with minus 1. That is used for support investigations. 
		this.deletingIndex = -1;
	}
	
	/**
	 * This method is used to add new User to the System. Therefore the are some handover values needed. 
	 * Below this values are precisely described.
	 * the system message (@return) gives a user more information about the adding process. For example the 
	 * message inform you that the user already exist or that the firstname is missing.
	 * 
	 * 
	 * @param 	firstName Is used for the first name of a User. 
	 * @param	lastName Is used for the last name of a User.
	 * @param 	userName Is used for the user name of a User.
	 * @return 	a String with the system message. 
	 */
	public String addUser (String firstName, String lastName, String userName){
		//this local variable is a string type which is instantiate with "error"
		//"error" message serves for support investigation as well. 
		String message = "error";
		
		//this local variable is a string typ, too. It just stores an empty string.
		// this is used to compare the empty strings by the adding process.
		String emtpy = "";
		
		//"addSuccessful saves a boolean value.
		//false = add new User to the ArrayList fails.
		//true 	= User adding was successful.
		boolean addSuccessful = false;
		
		//if-query, which checks the first name. If the first name is empty the message with
		//the value "First name can not be empty" will be returned.
		if(firstName.equalsIgnoreCase(emtpy)){
			//the local variable "message" will be overwritten.
			message = "First name can not be empty";
			//the return command end this method at this point.
			return message;
		}
		
		//if-query, which checks the last name. If the last name is empty the message with
		//the value "Last name can not be empty" will be returned.
		if(lastName.equalsIgnoreCase(emtpy)){
			//the local variable "message" will be overwritten.
			message = "Last name can not be empty";
			//the return command end this method at this point.
			return message;
		}
		
		//if-query, which checks the user name. If the user name is empty the message with
		//the value "Last name can not be empty" will be returned
		if(userName.equalsIgnoreCase(emtpy)){
			//the local variable "message" will be overwritten.
			message = "User name can not be empty";
			//the return command end this method at this point.
			return message;
		}
		
		//if-query which checks the length and just allows an user name below 10 token.
		if(userName.length() > 10){
			//the local variable "message" will be overwritten.
			message = "User name is too long. There is only 10 charaters allowed";
			//the return command end this method at this point.
			return message;
		}
		
		//if-query which checks the user name. If the user name already exist a message will be generated
		//and the method stops at this point.
		if(this.equals(userName) == true){
			//the local variable "message" will be overwritten.
			message = "User already exist";
			//the return command end this method at this point.
			return message;
		}
		
		//After all checks the user will be created and addes to the ArrayList "userList"
		//if the adding process was successful, "true" will be saved in the local variable "addSuccessful".
		//Otherwise "false" will be saved in there.
		addSuccessful = userList.addUser(new User (lastName,  firstName,  userName));
		
		//if the adding process successful proceeded, the program will create the message "user successful added"
		//by checking the local variable "addSuccessful".
		//At a further step a nes L
		if (addSuccessful == true){
			//the local variable "message" will be overwritten.
			message = "user successful added";
			//this.langList = new LanguageList();
			//this.dataHandlingIO = new DataHandlingIO(langList);
			//dataHandlingIO.startUp(userName);
		}	
			//If everything is going successful the message will be returned at this point.
			return message;
		}
	
	/**
	 * this is a method for updating the WelcomScreen if something have changed.
	 */
	public void update() {
		//calls a method from the class WelcomScreen. 
		welcomScreen.update();
	}
	
	/**
	 * A method which is need to showing system information. that could be an error or an operation that
	 * successful ends.
	 * 
	 * @param actualMsg		This handover string contains the information, which will be displayed at the screen.
	 */
	public void printMessage(String actualMsg) {
		//create a new instance of Message. It is stored in the local variable "message".
		//The handover value is the string which this method request.
		this.message = new Message(actualMsg);
		//Make the message windows visible.
		this.message.paint();
	}
	
	
	/**
	 * This method is used in the adding process and check if an user already exist.
	 * 
	 * @param userName	A string which contains an user name. 
	 * @return			boolean value:	true	=	user name already exist.
	 * 									false	=	user name doesn't exist.
	 */
	public boolean equals(String userName){
		//local variable storing temporary each element of the ArrayList "User".
		User tempUser;
		//local variable storing temporary each user name of all members / added User.
		String tempString;
		//A for-loop runs through the whole userList.
		for(int c = 0; c<userList.getSize(); c++){
			//safes the element with the index c. c grows every loop session by one step.
			tempUser = userList.getUser(c);
			//After saving an user element the step below stores the user name into "tempString".
			tempString = tempUser.getUsername();
			//an if-query which equals the user names. if they match "true" will be returned.
			if(userName.equalsIgnoreCase(tempString)){
				// the method stops at this point if the user names match.
				return true;
			}
		}
			//return "false" if the user name doesn't exist yet.
			return false;
		}

	/**
	 * this method is used to get the last name of a specific user.
	 * Therefore an index is needed and a String which contains the information will be returned
	 * 
	 * 
	 * @param index		an integer which select an user at specific index.
	 * @return			a string which contains the last name.
	 */
	public String getLastName(int index){
		//local variable which hold temporally a string token.
		String temp;
		//local variable which hold temporally an user reference.
		User tempUser;
		//pick out a user reference at the index, which is handovered before.
		tempUser = userList.getUser(index);
		//pick out the last name of the temporally stored user reference "tempUser".
		temp = tempUser.getLastname();
		//return the sting variable "temp".
		return temp;
	}
	
	/**
	 * this method is used to get the first name of a specific user.
	 * Therefore an index is needed and a String which contains the information will be returned
	 * 
	 * 
	 * @param index		an integer which select an user at specific index.
	 * @return			a string which contains the fist name.
	 */
	public String getFirstName(int index){
		//local variable which hold temporally a string token.
		String temp;
		//local variable which hold temporally an user reference.
		User tempUser;
		//pick out a user reference at the index, which is handovered before.
		tempUser = userList.getUser(index);
		//pick out the fist name of the temporally stored user reference "tempUser".
		temp = tempUser.getFirstname();
		//return the sting variable "temp".
		return temp;
	}
	
	/**
	 * this method is used to get the user name of a specific user.
	 * Therefore an index is needed and a String which contains the information will be returned
	 * 
	 * 
	 * @param index		an integer which select an user at specific index.
	 * @return			a string which contains the user name.
	 */
	public String getUserName(int index){
		//local variable which hold temporally a string token.
		String temp;
		//local variable which hold temporally an user reference.
		User tempUser;
		//pick out a user reference at the index, which is handovered before.
		tempUser = userList.getUser(index);
		//pick out the user name of the temporally stored user reference "tempUser".
		temp = tempUser.getUsername();
		//return the sting variable "temp".
		return temp;
	}
	
	/**
	 * This method is use do delete an user. In a later version of a program additional words from the
	 * specific user, which will be deleted, will also be deleted.
	 * But at the current version, just the user will be deleted!
	 * 
	 * This method dealing with Exception. The idea behind this is to be sure, that no exception can stop
	 * the program when an illegal index is used.
	 * 
	 * @param index		an integer which select an user at specific index.
	 * @return			a string which contains the a system information.
	 */
	public String deleteUser(int index){
		//String variable which is initialized with a "error" token.
		String message = "Error";
		//String variable which is initialized with a "error" token.
		String message2 = "Error";
		//for support investigation this command shows the handovered index.
		System.out.println("index: "+index);
		//here starts the try Block
		try{
			//if query which make sure that the index is bigger than the arraySize from "userList"
			if (index < userList.getSize()){
				//deletes an user reference at a specific index.
				userList.deleteUser(index);
				//save a system information into the local variable "message".
				message = "user successful deleted";
				//return the message and the end the method at this point, but just if
				//the deleting process was successful.
				return message;
			}
		}
		//here starts the catch block. It catch all exceptions.
		catch (Exception e){
			//the first message contains a information which is for the user.
			message = "index doesn't exist";
			//the second message contains support information.
			message2 = e.getMessage();
			//both message will be returned.
			return message + message2;
		}
		//this return statement should never be used.
		return message;
	}	
	
	
	/**
	 * This method is used for adding new words to the to the languageList. Its very important, that all
	 * four language will be added at the same time.
	 * 
	 * 
	 * @param handover		This string should contains username, word-DE, word-EN, word-FR. word-IT
	 */
	public void addWord(String handover){
		//creats a String array, which stores the splitted contain.
		//The string will be splitted by "," token.
		String[] parts = handover.split(",");
		//There the user name will be stored.
		String user = parts[0];
		//There the German word will be stored.
		String german = parts[1];
		//There the English word will be stored.
		String english= parts[2];
		//There the French word will be stored.
		String french = parts[3];
		//There the Italian word will be stored.
		String italian = parts[3];
		//First a new primaryKey will be generated
		//it will be temporally stored @ the int local variable.
		int newPrimaryKey = this.dataHandlingIO.generateNewLangPriKey();
		//A new languae will be created and later added to the langList.
		langList.addLanguage(new Language(german, 1, newPrimaryKey, 1, user));
		langList.addLanguage(new Language(english, 2, newPrimaryKey, 1, user));
		langList.addLanguage(new Language(french, 3, newPrimaryKey, 1, user));
		langList.addLanguage(new Language(italian, 4, newPrimaryKey, 1, user));
		
	}
	
	/**
	 * This method has the main function to search a word in the arrayList. If the method find the word,
	 * it will store the index into the data field d"deletingIndex.
	 * 
	 *  As you can see, you have to query this method first, before you query the "deleteWord" method.
	 * 
	 * @param handover		A single word is enough for searching it in an arryList (langList)
	 * @return				if the method find the word, it will return true. In the other case it will return false.
	 */
	public boolean searchWord(String handover){
		//stores the boolean value. it is initialized with "false".
		boolean found = false;
		//now the handovered word will transform to upper case.
		String searchingWord = handover.toUpperCase();
		//A for Loop, which runs through the whole arrayList.
		for (int i = 0; i < langList.getSize(); i++){
			//safes the element with the index i. i grows every loop session by one step.
			Language temp = langList.getlang(i);
			//now the temp word will transform to upper case.
			String tempWord = temp.getWord().toUpperCase();
			//if Query which equals the tempWord and the handoverd word
			if(tempWord.equals(searchingWord)){
				//now the index will be stored.
				deletingIndex = i;
				//the "found" to "true", if the word is found. 
				found = true;
			}
				
		}
		//return the boolean value from the local variable "found".
		return found;
	}
	
	/**
	 * This method is used to delete a word from the userList.
	 * 
	 * @param handover		A single word is enough for searching it in an arryList (langList)
	 * @return				if the method find the word, it will return true. In the other case it will return false.
	 */
	public boolean deleteWord(String handover){
		//First the program has to check the word and search the index from a specific word.
		this.searchWord(handover);
		//stores the boolean value. it is initialized with "false".
		boolean deleted = false;
		//an Boolean Array with a length of 3 will created here and all fields are initialized with false. 
		Boolean[] allDeleted = null;
		allDeleted = new Boolean[3];
		Arrays.fill(allDeleted, Boolean.FALSE);
		//3 additional indexes are needed for deleting a word in each language. 
		int index1 = -1;
		int index2 = -1;
		int index3 = -1;
		//stores a language reference from the "deletingIndex"
		Language temp = langList.getlang(deletingIndex);
		//store the primary key from the "deleting word" stored word.
		int deletingPrimaryKey = temp.getPrimaryKey();
		//A for Loop, which runs through the whole arrayList.
		for (int i = 0; i < langList.getSize(); i++){
			//safes the element with the index i. i grows every loop session by one step.
			Language temp2 = langList.getlang(i);
			//if query which compare the primary Key of each element.
			if(deletingPrimaryKey == temp2.getPrimaryKey()){
				//The program supports three language. Therefore weed need three indexes. 
				//The first index which the program finds, will be stored in "index1". The next one will be stored
				//in "index2". and so on. The boolean value is for checking the amount of found words. 
				if(index1 == -1){
					index1 = i;
					allDeleted[0] = true;
				}
				if(index2 == -1){
					index2 = i;
					allDeleted[1] = true;
				}
				if(index3 == -1){
					index3 = i;
					allDeleted[2] = true;
				}
			}
		}
		//this if qurey makes sure, that all 3 additional indexes are found. 
		//If this is not true, no words will delete.
		if ((allDeleted[0] == true) && (allDeleted[1] == true) && (allDeleted[3] == true)){
			langList.deleteLanguage(deletingPrimaryKey);
			langList.deleteLanguage(index1);
			langList.deleteLanguage(index2);
			langList.deleteLanguage(index3);
			deleted = true;
		}
		//return the boolean value from the local variable "deleted".
		return deleted;
	}
	
	public UserList getUserList(){
		return this.userList;
	}
	
	/**
	 * As it the name of this method says, is it used for start the the game.
	 * 
	 * The requested index is in this version NOT implemented. Later it will be used to
	 * load the additional words from a specific user.
	 * 
	 * @param index		index (int value) from the playing user.
	 * @param la		reference of Languages.
	 */
	public void startGame(int index, Languages la){
		//load a user reference into the "temp".
		User temp = userList.getUser(index);
		//load all information from the playing user und creates an new instance of ActiveUser.
		//After this the new Active User will be stored into the local data field "activeUser".
		this.activeUser = new ActiveUser(temp.getLastname(), temp.getFirstname(), temp.getUsername(),langList);
		//A new window will be started, which is responsible for the "game".
		//the new ICoachScreen required an Activeusere and language reference.
		new ICoachScreen(activeUser, la);
		}
	
	/**
	 * This method saves the current users and templates.
	 */
	public void saveGame(){
		//First the language will be saved
		this.dataHandlingIO.exportLang(langList);
		//Second the users will be saved
		this.dataHandlingIO.exportUser(userList);
	}
	
	/**
	 * This method load the specific langList
	 */
	public void loadGame(){
		this.dataHandlingIO.importLang();
	}
	
	/**
	 * Loads the stored userList.
	 */
	public void loadUsers(){
		this.dataHandlingIO.importUser();
	}
}
